package com.creali.web.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;


/**
 * 因为hibernate的session是非线程安全，管理session非常重要，对于单个业务进程或单个工作单元，都一次用完session后就关闭它，
 * 这样只可以达到session相关的缓存数据同步到数据库<br>
 * 继承sprng
 * 的hibernateDaoSupport其利用spring的hibernateTemplate来提供hibernate的session管理方案
 * 使用hibernate会自动获取与当前线程相关的session 在调用结束后，spring会自动关闭session<br>
 * About Session lifecycle in hibernate: The lifecycle of a <tt>Session</tt> is
 * bounded by the beginning and end of a logical transaction. (Long transactions
 * might span several database transactions.)<br>
 * 
 * @author Administrator
 * 
 * @param <T>
 * @param <PK>
 */
@Repository
public class GenericHibernateDao<T, PK extends Serializable> extends
		HibernateDaoSupport implements GenericHibernateDaoI<T, PK> {
	
	private Class<T> persistentClass;
	
	@Autowired  
    public void setSessionFactoryOverride(org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean sessionFactory){  
        super.setSessionFactory(sessionFactory.getObject());  
    }  	

	public GenericHibernateDao() {
		super();
	}

	public GenericHibernateDao(Class<T> persistentClass) {
		super();
		this.persistentClass = persistentClass;
	}

	@SuppressWarnings("unchecked")
	public T get(final PK id) {
		T entity = (T) super.getHibernateTemplate().get(this.persistentClass,
				id);
		if (entity == null) {
			throw new ObjectRetrievalFailureException(this.persistentClass, id);
		}
		return entity;
	}

	public List<T> getAll() {
		return super.getHibernateTemplate().loadAll(this.persistentClass);
	}

	public void deleteByUserId(PK id) {
		super.getHibernateTemplate().delete(this.get(id));
	}

	@SuppressWarnings("unchecked")
	public void save(final T entity) {
		super.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				session.save(entity);
				return null;
			}
		});
	}

	public void deleteGivenPersistentClass(T entity) {
		super.getHibernateTemplate().delete(entity);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<T> findByProperty(final String entityName,
			final String propertyName, final Object propertyValue) {

		return (List<T>) super.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String queryString = "From " + entityName
								+ " as model where model." + propertyName
								+ "= :propertyValue";
						Query queryObject = session.createQuery(queryString);
						queryObject.setParameter("propertyValue", propertyValue);
						return queryObject.list();
					}
				});
	}

}
